<?php
/**
 * Created by PhpStrom
 * User: 郭碧云
 * Date: 2021/6/8 11:03
 * Desc:
 */

namespace App\Service;

use App\Lib\Logger;
use App\Models\CategoryGroup;
use App\Models\Tag;
use App\Models\TagGroup;
use App\Models\TagGroupTag;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

class TagService extends BaseService
{
    protected $modelName="Tag";
    /**
     * @var string 标签设置缓存KEY
     */
    protected $cachePrefix = 'TAG_GROUP_';

    /**
     * @var float|int 缓存有效期
     */
    protected $ttl = 60 * 60 * 24 * 5;//5天

    /**
     * 新增标签
     * @param $tag
     * @return mixed
     */
    public function add($tag) {
        $tag = (new Tag())->create($tag)->toArray();
        $this->log(Logger::LOG_LEVEL_INFO, Logger::TAG, 'create', "新增标签[ID:" . $tag['id'] . "],成功", $tag);
        return $tag;
    }

    /**
     * 编辑标签
     * @param $id
     * @param $tag
     * @return mixed
     */
    public function update($id, $tag) {
        $tag = Tag::where("id", $id)->update($tag);
        $this->log(Logger::LOG_LEVEL_INFO, Logger::TAG, 'update', "修改标签[ID:{$id}],成功", $tag);
        return $tag;
    }

    /**
     * 删除标签
     * @param $id
     */
    public function destroy($id) {
        $result = Tag::where("id", $id)->delete();
        $this->log(Logger::LOG_LEVEL_INFO, Logger::TAG, 'delete', "删除标签[ID:{$id}],成功", "");
        return $result;
    }


    /**
     * 根据ID查询标签
     * @param $id
     * @return |null
     */
    public function getTagById($id) {
        $tag = Tag::find($id);
        if ($tag) {
            return $tag->toArray();
        }
        return null;
    }

    /**
     * 获取标签列表
     * @param $where
     * @return mixed
     */
    public function getTagList($where) {
        return (new Tag())->whereBuilder($where)->get()->toArray();
    }

    /**
     * 新增标签组
     * @param $tagGroup
     * @return mixed
     */
    public function addGroup($tagGroup) {
        $tagGroup = (new TagGroup())->create($tagGroup)->toArray();
        $this->cache($tagGroup['id']);
        $this->log(Logger::LOG_LEVEL_INFO, Logger::TAG, 'create', "新增标签组[ID:" . $tagGroup['id'] . "],成功", $tagGroup);
        return $tagGroup;
    }

    /**
     * 编辑标签组
     * @param $id
     * @param $tagGroup
     * @return mixed
     */
    public function updateGroup($id, $tagGroup) {
        $tagGroup = TagGroup::where("id", $id)->update($tagGroup);
        $this->cache($id);
        $this->log(Logger::LOG_LEVEL_INFO, Logger::TAG, 'update', "修改标签[ID:{$id}],成功", $tagGroup);
        return $tagGroup;
    }

    /**
     * 删除标签组
     * @param $id
     */
    public function destroyGroup($id) {
        $result = TagGroup::where("id", $id)->delete();
        $this->destroyGroupTag($id);
        $this->log(Logger::LOG_LEVEL_INFO, Logger::TAG, 'delete', "删除标签[ID:{$id}],成功","");
        return $result;
    }

    /**
     * 删除标签组中的标签
     */
    private function destroyGroupTag($group_id){
        TagGroupTag::where("group_id", $group_id)->delete();
    }

    /**
     * 标签组里添加标签
     * @param $data
     *
     * @补充说明：2021-06-15 郭碧云 填充
     */
    public function addTagGroupTag($group_id,$params) {

        //获取分配标签数据
        $data=[];
        foreach ($params["tag_id"] as $k => $v){
            $data[$k]["group_id"]=$group_id;
            $data[$k]["tag_id"]=$v;
            $data[$k]["sort"]=$params["sort"][$k];
        }
        $tagAndGroup = (new TagGroupTag())->insertOrIgnore($data);
        $this->log(Logger::LOG_LEVEL_INFO, Logger::TAG, 'groupStore', "给标签组[ID:" . $group_id . "]添加标签,成功", $data);
        return $tagAndGroup;
    }

    /**
     * 更新标签组中的标签
     */
    public function updateTagInGroup($group_id,$params){
        (new TagGroupTag())->where("group_id",$group_id)->delete();
        return $this->addTagGroupTag($group_id,$params);
    }

    /**
     * 根据ID查询标签组
     * @param $id
     * @return |null
     */
    public function getTagGroupById($id) {
        $tagGroup = TagGroup::find($id);
        if ($tagGroup) {
            return $tagGroup->toArray();
        }
        return null;
    }

    /**
     * 获取标签组列表
     * @param int $scopeId 标签组范围
     * @param int $siteId 站点ID
     * @return mixed
     */
    public function getTagGroupList($scopeId, $siteId = 0) {
        return $this->getTagGroupAll($scopeId, $siteId);
    }

    /**
     * 按范围查询标签组
     * @param $scopeId
     * @param $siteId
     * @return mixed
     */
    private function getTagGroupAll($scopeId = 0, $siteId = 0) {
        $where = [];
        if (!getCurrentSiteId() && $siteId) {
            $where['site_id'] = $siteId;
        }
        if ($scopeId) {
            return (new TagGroup())->whereBuilder($where)->whereRaw("FIND_IN_SET({$scopeId},`scope`)")->get()->toArray();
        } else {
            return (new TagGroup())->whereBuilder($where)->get()->toArray();
        }
    }

    /**
     * 通过缓存按照ID获取标签组
     * @param $groupId 标签组ID
     * @return mixed
     */
    public function getTagGroupByGroupId($groupId) {
        $tagGroup = Cache::get($this->cacheKey($groupId));
        if (!$tagGroup) {
            $tagGroup = $this->cache($groupId);
        }
        return $tagGroup;
    }

    /**
     * 生成缓存KEY
     * @param int $groupId 分类分组ID
     * @param int $siteId 站点ID
     * @return string
     */
    private function cacheKey($groupId) {
        return $this->cachePrefix . $groupId;
    }

    private function cacheScopeKey($scopeId, $siteId = 0) {
        if (!getCurrentSiteId() && $siteId) {
            $siteId = ['site_id', '=', $siteId];
        } else {
            $siteId = getCurrentSiteId();
        }
        return "TAG_SCOPE_{$siteId}_{$scopeId}";
    }

    private function cacheScopeTagGroupIds($siteId = 0) {
        $scopeList = (new CategoryService())->getCategoryGroupList();
        $tagGroupList = $this->getTagGroupAll(0, $siteId);
        if (!getCurrentSiteId() && $siteId) {
            $siteId = ['site_id', '=', $siteId];
        } else {
            $siteId = getCurrentSiteId();
        }
        $scopeCache = [];
        foreach ($tagGroupList as $tagGroup) {
            $tagGroupScope = explode(',', $tagGroup['scope']);
            foreach ($scopeList as $scope) {
                if (in_array($scope['id'], $tagGroupScope)) {
                    $scopeCache[$scope['id']][$tagGroup['id']] = $tagGroup['id'];
                }
            }
        }
        foreach ($scopeCache as $key => $value) {
            $cacheKey = $this->cacheScopeKey($key, $siteId);
            Cache::put($cacheKey, $value, $this->ttl);
        }
    }

    /**
     * 按照使用范围获取标签组列表
     * @param $scopeId 使用范围ID
     * @param int $siteId
     * @return array
     */
    public function getTagGroupByScopeId($scopeId, $siteId = 0) {
        $cacheKey = $this->cacheScopeKey($scopeId, $siteId);
        $tagGroupIds = Cache::get($cacheKey);
        if (!$tagGroupIds) {
            $this->cacheScopeTagGroupIds($siteId);
            $tagGroupIds = Cache::get($cacheKey);
        }
        $tagGroup = [];
        foreach ($tagGroupIds as $tagGroupId) {
            $tagGroup[] = $this->getTagGroupByGroupId($tagGroupId);
        }
        return $tagGroup;
    }

    /**
     * @param int $groupId
     * @param int $siteId
     * @return mixed
     */
    public function cache($groupId = 0, $siteId = 0) {
        if (!getCurrentSiteId() && $siteId) {
            $where['site_id'] = $siteId;
        }
        if ($groupId) {
            $tagGroup = TagGroup::find($groupId);
            if ($tagGroup) {
                $cacheKey = $this->cacheKey($groupId, $siteId);
                $tagGroup = $tagGroup->toArray();
                Cache::put($cacheKey, $tagGroup, $this->ttl);
                return $tagGroup;
            }
        } else {
            if ($siteId) {
                $tagGroups = $this->getTagGroupAll(0, $siteId);
                foreach ($tagGroups as $group) {
                    $cacheKey = $this->cacheKey($group['id']);
                    Cache::put($cacheKey, $group, $this->ttl);
                }
            } else {
                return null;
            }
        }
    }

    /**
     * 获取下拉标签组
     * @param $info 标签信息
     * @author 郭碧云
     */
    public function tagGroupSelect($info) {
        $tags = $this->getTagGroupByScopeId($info['group_id']);
        //添加选中部分
        if (!empty($info["course_tag_group"])) {
            $values = Arr::pluck($info["course_tag_group"], "id");
            foreach ($tags as $k => $v) {
                if (in_array($v["id"], $values)) {
                    $tags[$k]["selected"] = true;
                }
            }
        }
        return $tags;
    }

    /**
     * 获取标签列表
     * @param $where条件
     * @author 郭碧云
     */
    public function getTagList2($where) {
        $data = (new Tag())->whereBuilder($where)->with(["tagAndGroup"])->get()->toArray();
        return $this->getArrToStr($data, "tag_and_group", "name", "groupName");
    }

    /**
     * 获取经由array转字符串
     * 给定格式字符串
     * @param $data 提取的二维数组
     * @param $group 提取的二维数组中的哪个字段
     * @param $key 提取的关键字段
     * @param $name 返回存储到二维数组中的名称
     * @author 郭碧云
     */
    public function getArrToStr($data, $group, $key, $name) {
        if ($group == "" || empty($group)) {
            $temp = Arr::pluck($data, "{$key}");
            $newTemp = array_map(function ($item) {
                return '【' . $item . "】";
            }, $temp);
            $data["{$name}"] = implode(',', $newTemp);

        } else {
            foreach ($data as $k => $tag) {
                $temp = Arr::pluck($tag["{$group}"], "{$key}");
                $newTemp = array_map(function ($item) {
                    return '【' . $item . "】";
                }, $temp);
                $data[$k]["{$name}"] = implode(',', $newTemp);
            }
        }

        return $data;
    }

    /**
     * 获取标签组数据
     * @param $params 表单提交的数据
     * @author 郭碧云
     */
    public function getGroupData($params){
        //获取tags
        $params["tag_num"]=count($params["tag_id"]);
        $params["site_id"] = getCurrentSiteId();
        $params["scope"] = implode(",",$params["scope"]);
        return Arr::only($params,(new TagGroup())->getUpdateData());
    }

    /**
     * 获取应用范围
     * category_group
     * @param $groupId 分组id字符串 如:1,2
     * @author 郭碧云
     */
    public function getScope($groupId = "") {
        if ($groupId == "") {
            $scope = (new CategoryGroup())->get();
        } else {
            $scope = (new CategoryGroup())->whereIn("id", explode(",", $groupId))->get();
        }
        return empty($scope) ? [] : $scope->toArray();
    }

    /**
     * 获取已有的标签组所有信息
     * @param $info 标签组已有的范围
     */
    public function info($id){
        $info = $this->getTagGroupById($id);
        $scopeArr = $this->getScope();
        $tagList = $this->getTagList([]);
        $info["scope"]=$this->scope($info["scope"],$scopeArr);
        $info["tagsSelect"]=$this->tagsSelect($info["tags"],$tagList);
        return $info;
    }

    /**
     * 获取选中的范围
     * @param $scope 拥有的适用范围
     * @param $scopeArr 所有可用的使用范围
     * @author 郭碧云
     */
    private function scope($scope,$scopeArr){
        $temp = explode(",",$scope);
        foreach ($scopeArr as $k=>$s){
            if(in_array($s["id"],$temp)){
                $scopeArr[$k]["checked"]=true;
            }
            else{
                $scopeArr[$k]["checked"]=false;
            }
        }
        return $scopeArr;
    }

    /**
     * 获取选中的范围
     * @param $scope 拥有的适用范围
     * @param $scopeArr 所有可用的使用范围
     * @author 郭碧云
     */
    private function tagsSelect($tags,$tagList){
        $temp = Arr::pluck($tags,"id");
        foreach ($tagList as $k=>$tag){
            if(in_array($tag["id"],$temp)){
                $tagList[$k]["selected"]=true;
            }
        }
        return $tagList;
    }
}
